<?php
/**
 * Created by PhpStorm.
 * User: b0zar
 * Date: 12/26/13
 * Time: 9:41 PM
 */

namespace Iaem\UserBundle\Service;


use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUser;
use Iaem\UserBundle\Entity\User;
use Symfony\Component\HttpKernel\Tests\ControllerResolverTest;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;

class Provider implements UserProviderInterface, OAuthAwareUserProviderInterface
{
    /**
     * @var \Doctrine\ORM\EntityManager
     */
    private $em;

    /**
     * Get EntityManager
     *
     * @param $em
     */
    public function __construct($em)
    {
        $this->em = $em;
    }

    /**
     * Loads the user for the given username.
     *
     * This method must throw UsernameNotFoundException if the user is not
     * found.
     *
     * @param string $username The username
     *
     * @return UserInterface
     *
     * @see UsernameNotFoundException
     *
     * @throws UsernameNotFoundException if the user is not found
     *
     */
    public function loadUserByUsername($username)
    {
        return $this->em->getRepository('Iaem\UserBundle\Entity\User')->findOneBy(['nickname' => $username]);
    }

    /**
     * Refreshes the user for the account interface.
     *
     * It is up to the implementation to decide if the user data should be
     * totally reloaded (e.g. from the database), or if the UserInterface
     * object can just be merged into some internal array of users / identity
     * map.
     * @param UserInterface $user
     *
     * @return UserInterface
     *
     * @throws UnsupportedUserException if the account is not supported
     */
    public function refreshUser(UserInterface $user)
    {
        if (!$this->supportsClass(get_class($user))) {
            throw new UnsupportedUserException(sprintf('Unsupported user class "%s"', get_class($user)));
        }

        return $this->loadUserByUsername($user->getNickname());
    }

    /**
     * Whether this provider supports the given user class
     *
     * @param string $class
     *
     * @return Boolean
     */
    public function supportsClass($class)
    {
        return $class === 'Iaem\UserBundle\Entity\User';
    }


    /**
     * Loads the user by a given UserResponseInterface object.
     *
     * @param UserResponseInterface $response
     *
     * @return UserInterface
     *
     * @throws UsernameNotFoundException if the user is not found
     */
    public function loadUserByOAuthUserResponse(UserResponseInterface $response)
    {
        $user = $this->em->getRepository('Iaem\UserBundle\Entity\User')->findOneBy([
            'nickname' => $response->getNickname(),
            'type' => $response->getResourceOwner()->getName()
        ]);
        if (!($user instanceof User)) {
            $user = new User();
            $user->setNickname($response->getNickname());
            $user->setType($response->getResourceOwner()->getName());
            $user->setUsername($response->getUsername());
            $user->setAccessToken($response->getAccessToken());
            $user->setTokenSecret($response->getTokenSecret());
            $user->setRefreshToken($response->getAccessToken());
            $user->setRealName($response->getRealName());
            $user->setEmail($response->getEmail());

            $this->em->persist($user);
            $this->em->flush();
        }
        return $user;
    }
}
